﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
/*
 * Project Home : http://code.google.com/p/klsudoku
 * Project Owner: ttylikl@gmail.com Email:ttylikl@qq.com
 * Project Blog : http://www.cnblogs.com/ttylikl
 * All Files of this project is free to use , but you should keep the information above when you copy&use it.
 * Infomation Modify Date: 2009.02.22
 * 
 * */

namespace SudokuPanel
{
    public static class pubfun
    {
        public enum Flag { none, normal, tag };
        public static Point[] basepoints = new Point[9]{
                new Point(1,1),new Point(4,1),new Point(7,1),
                new Point(1,4),new Point(4,4),new Point(7,4),
                new Point(1,7),new Point(4,7),new Point(7,7)};
        public static String[] zname = new String[9] {  "左上九宫","上九宫","右上九宫","左九宫","中九宫","右九宫","左下九宫","下九宫","右下九宫"};
        public readonly static int[,] comb2 = new int[,] { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 6 }, { 1, 7 }, { 1, 8 }, { 2, 3 }, { 2, 4 }, { 2, 5 }, { 2, 6 }, { 2, 7 }, { 2, 8 }, { 3, 4 }, { 3, 5 }, { 3, 6 }, { 3, 7 }, { 3, 8 }, { 4, 5 }, { 4, 6 }, { 4, 7 }, { 4, 8 }, { 5, 6 }, { 5, 7 }, { 5, 8 }, { 6, 7 }, { 6, 8 }, { 7, 8 }, };
        public readonly static int[,] comb3 = new int[,] { { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 1, 5 }, { 0, 1, 6 }, { 0, 1, 7 }, { 0, 1, 8 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 2, 5 }, { 0, 2, 6 }, { 0, 2, 7 }, { 0, 2, 8 }, { 0, 3, 4 }, { 0, 3, 5 }, { 0, 3, 6 }, { 0, 3, 7 }, { 0, 3, 8 }, { 0, 4, 5 }, { 0, 4, 6 }, { 0, 4, 7 }, { 0, 4, 8 }, { 0, 5, 6 }, { 0, 5, 7 }, { 0, 5, 8 }, { 0, 6, 7 }, { 0, 6, 8 }, { 0, 7, 8 }, { 1, 2, 3 }, { 1, 2, 4 }, { 1, 2, 5 }, { 1, 2, 6 }, { 1, 2, 7 }, { 1, 2, 8 }, { 1, 3, 4 }, { 1, 3, 5 }, { 1, 3, 6 }, { 1, 3, 7 }, { 1, 3, 8 }, { 1, 4, 5 }, { 1, 4, 6 }, { 1, 4, 7 }, { 1, 4, 8 }, { 1, 5, 6 }, { 1, 5, 7 }, { 1, 5, 8 }, { 1, 6, 7 }, { 1, 6, 8 }, { 1, 7, 8 }, { 2, 3, 4 }, { 2, 3, 5 }, { 2, 3, 6 }, { 2, 3, 7 }, { 2, 3, 8 }, { 2, 4, 5 }, { 2, 4, 6 }, { 2, 4, 7 }, { 2, 4, 8 }, { 2, 5, 6 }, { 2, 5, 7 }, { 2, 5, 8 }, { 2, 6, 7 }, { 2, 6, 8 }, { 2, 7, 8 }, { 3, 4, 5 }, { 3, 4, 6 }, { 3, 4, 7 }, { 3, 4, 8 }, { 3, 5, 6 }, { 3, 5, 7 }, { 3, 5, 8 }, { 3, 6, 7 }, { 3, 6, 8 }, { 3, 7, 8 }, { 4, 5, 6 }, { 4, 5, 7 }, { 4, 5, 8 }, { 4, 6, 7 }, { 4, 6, 8 }, { 4, 7, 8 }, { 5, 6, 7 }, { 5, 6, 8 }, { 5, 7, 8 }, { 6, 7, 8 }, };
        public readonly static int[,] comb4 = new int[,] { { 0, 1, 2, 3 }, { 0, 1, 2, 4 }, { 0, 1, 2, 5 }, { 0, 1, 2, 6 }, { 0, 1, 2, 7 }, { 0, 1, 2, 8 }, { 0, 1, 3, 4 }, { 0, 1, 3, 5 }, { 0, 1, 3, 6 }, { 0, 1, 3, 7 }, { 0, 1, 3, 8 }, { 0, 1, 4, 5 }, { 0, 1, 4, 6 }, { 0, 1, 4, 7 }, { 0, 1, 4, 8 }, { 0, 1, 5, 6 }, { 0, 1, 5, 7 }, { 0, 1, 5, 8 }, { 0, 1, 6, 7 }, { 0, 1, 6, 8 }, { 0, 1, 7, 8 }, { 0, 2, 3, 4 }, { 0, 2, 3, 5 }, { 0, 2, 3, 6 }, { 0, 2, 3, 7 }, { 0, 2, 3, 8 }, { 0, 2, 4, 5 }, { 0, 2, 4, 6 }, { 0, 2, 4, 7 }, { 0, 2, 4, 8 }, { 0, 2, 5, 6 }, { 0, 2, 5, 7 }, { 0, 2, 5, 8 }, { 0, 2, 6, 7 }, { 0, 2, 6, 8 }, { 0, 2, 7, 8 }, { 0, 3, 4, 5 }, { 0, 3, 4, 6 }, { 0, 3, 4, 7 }, { 0, 3, 4, 8 }, { 0, 3, 5, 6 }, { 0, 3, 5, 7 }, { 0, 3, 5, 8 }, { 0, 3, 6, 7 }, { 0, 3, 6, 8 }, { 0, 3, 7, 8 }, { 0, 4, 5, 6 }, { 0, 4, 5, 7 }, { 0, 4, 5, 8 }, { 0, 4, 6, 7 }, { 0, 4, 6, 8 }, { 0, 4, 7, 8 }, { 0, 5, 6, 7 }, { 0, 5, 6, 8 }, { 0, 5, 7, 8 }, { 0, 6, 7, 8 }, { 1, 2, 3, 4 }, { 1, 2, 3, 5 }, { 1, 2, 3, 6 }, { 1, 2, 3, 7 }, { 1, 2, 3, 8 }, { 1, 2, 4, 5 }, { 1, 2, 4, 6 }, { 1, 2, 4, 7 }, { 1, 2, 4, 8 }, { 1, 2, 5, 6 }, { 1, 2, 5, 7 }, { 1, 2, 5, 8 }, { 1, 2, 6, 7 }, { 1, 2, 6, 8 }, { 1, 2, 7, 8 }, { 1, 3, 4, 5 }, { 1, 3, 4, 6 }, { 1, 3, 4, 7 }, { 1, 3, 4, 8 }, { 1, 3, 5, 6 }, { 1, 3, 5, 7 }, { 1, 3, 5, 8 }, { 1, 3, 6, 7 }, { 1, 3, 6, 8 }, { 1, 3, 7, 8 }, { 1, 4, 5, 6 }, { 1, 4, 5, 7 }, { 1, 4, 5, 8 }, { 1, 4, 6, 7 }, { 1, 4, 6, 8 }, { 1, 4, 7, 8 }, { 1, 5, 6, 7 }, { 1, 5, 6, 8 }, { 1, 5, 7, 8 }, { 1, 6, 7, 8 }, { 2, 3, 4, 5 }, { 2, 3, 4, 6 }, { 2, 3, 4, 7 }, { 2, 3, 4, 8 }, { 2, 3, 5, 6 }, { 2, 3, 5, 7 }, { 2, 3, 5, 8 }, { 2, 3, 6, 7 }, { 2, 3, 6, 8 }, { 2, 3, 7, 8 }, { 2, 4, 5, 6 }, { 2, 4, 5, 7 }, { 2, 4, 5, 8 }, { 2, 4, 6, 7 }, { 2, 4, 6, 8 }, { 2, 4, 7, 8 }, { 2, 5, 6, 7 }, { 2, 5, 6, 8 }, { 2, 5, 7, 8 }, { 2, 6, 7, 8 }, { 3, 4, 5, 6 }, { 3, 4, 5, 7 }, { 3, 4, 5, 8 }, { 3, 4, 6, 7 }, { 3, 4, 6, 8 }, { 3, 4, 7, 8 }, { 3, 5, 6, 7 }, { 3, 5, 6, 8 }, { 3, 5, 7, 8 }, { 3, 6, 7, 8 }, { 4, 5, 6, 7 }, { 4, 5, 6, 8 }, { 4, 5, 7, 8 }, { 4, 6, 7, 8 }, { 5, 6, 7, 8 }, };

        public static int str2int(String str)
        {
            try{
                return Int32.Parse(str);
            }
            catch(Exception)
            {
                return 0;
            }
        }
        public static String strIteratorName(iterator it)
        {
            Point head = it.begin().value().xy;
            Point tail = it.end().value().xy;
            if (head.X == tail.X)
                return "第" + head.X + "列";
            if (head.Y == tail.Y)
                return "第" + strRowName(head.Y) + "行";
            int x = (head.X - 1) / 3;
            int y = (head.Y - 1) / 3;
            return zname[y * 3 + x];
        }

        public static String strRowName(int row)
        {
            return "" +(char) ('A' + row - 1);
        }

        public static String strPoint(Point p)
        {
            return "" + strRowName(p.Y) + p.X; 
        }


        public static String strPoints(List<Point> ps)
        {
            String ret = "";
            foreach (Point p in ps)
            {
                ret += strPoint(p) + ",";
            }
            ret = ret.TrimEnd(',');
            return ret;
        }

        public static String strPoints(Point[] ps)
        {
            String ret="";
            foreach (Point p in ps)
            {
                ret += strPoint(p) + ",";
            }
            ret = ret.TrimEnd(',');
            return ret;
        }

        public static String strNumber(number num)
        {
            return "{" + strPoint(num.xy) + "=" + num.value + "|"+strListInt(num.candidates())+"}";
        }

        public static String strNumbers(List<number> nums)
        {
            String ret="";
            foreach (number num in nums)
            {
                ret += strNumber(num) + ",";
            }
            ret=ret.TrimEnd(',');
            return ret;
        }
        public static String strNumbers(number[] nums)
        {
            String ret = "";
            foreach (number num in nums)
            {
                ret += strNumber(num) + ",";
            }
            ret = ret.TrimEnd(',');
            return ret;
        }

        public static String strNumbersPoint(List<number> nums)
        {
            String ret = "";
            foreach (number num in nums)
            {
                ret += strPoint(num.xy) + ",";
            }
            ret = ret.TrimEnd(',');
            return ret;
        }
        public static String strNumbersPoint(number[] nums)
        {
            String ret = "";
            foreach (number num in nums)
            {
                ret += strPoint(num.xy) + ",";
            }
            ret = ret.TrimEnd(',');
            return ret;
        }

        public static String strListInt(List<int> nums)
        {
            String ret = "{";
            foreach( int num in nums)
            {
                ret += num+",";
            }
            ret=ret.TrimEnd(',');
            ret += "}";
            return ret;

        }
        public static String strListInt(int[] nums)
        {
            String ret = "{";
            foreach (int num in nums)
            {
                ret += num + ",";
            }
            ret = ret.TrimEnd(',');
            ret += "}";
            return ret;
        }

        public static bool isSameBlock(Point p1, Point p2)
        {
            return ((p1.X - 1) / 3 == (p2.X - 1) / 3 && (p1.Y - 1) / 3 == (p2.Y - 1) / 3);
        }
        public static bool isSameRow(Point p1, Point p2)
        {
            return (p1.Y == p2.Y);
        }
        public static bool isSameCol(Point p1, Point p2)
        {
            return (p1.X == p2.X);
        }

        public static bool isValidPoint(Point p)
        {
            if (1 <= p.X && p.X <= 9 && 1 <= p.Y && p.Y <= 9)
                return true;
            return false;
        }

        public static bool isValidIndex(int val)
        {
            if (0 <= val && val < 9)
                return true;
            return false;
        }

        public static bool isValidValue(int val)
        {
            if (0 < val && val <= 9)
                return true;
            return false;
        }

        public static object CloneObject(object obj)
        {
            MemoryStream ms = new MemoryStream();
            object CloneObject;
            BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
            bf.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            CloneObject = bf.Deserialize(ms);
            ms.Close();
            return CloneObject;
        }

        public static readonly char[] tbl = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();

        public static String deflatePuzzle(String str)
        {
            StringBuilder sb = new StringBuilder();
            String temp=str.Replace("\r\n", "");
            if (temp.Length != 81)
                throw new Exception("Wrong puzzle string!");
            char[] chs = temp.ToCharArray();
            return temp;
        }

        //两个数格数组的合集
        public static List<number> numbers_collection(number[] ns1, number[] ns2)
        {
            List<number> ret = new List<number>();
            ret.InsertRange(0, ns2);
            foreach (number n1 in ns1)
            {
                bool notexist = true;
                foreach (number n2 in ns2)
                {
                    if (n1.xy == n2.xy)
                    {
                        notexist = false;
                        break;
                    }
                }
                if (notexist)
                    ret.Add(n1);
            }
            return ret;
        }
        //两个数格数组的交集
        public static List<number> numbers_intersection(number[] ns1, number[] ns2)
        {
            List<number> ret = new List<number>();
            if (ns1.Length == 0 || ns2.Length == 0)
                return ret;
            foreach (number n1 in ns1)
            {
                foreach (number n2 in ns2)
                {
                    if (n1.xy == n2.xy)
                    {
                        ret.Add(n1);
                        break;
                    }
                }
            }
            return ret;
        }

        public static List<int> intersection_int(List<int> nla, List<int> nlb)
        {
            List<int> nl = new List<int>();
            foreach (int na in nla)
            {
                foreach (int nb in nlb)
                    if (na == nb)
                        nl.Add(nb);
            }
            return nl;
        }
        public static List<int> intersection_int(List<int> nla, int[] nlb)
        {
            List<int> nl = new List<int>();
            foreach (int na in nla)
            {
                foreach (int nb in nlb)
                    if (na == nb)
                        nl.Add(nb);
            }
            return nl;
        }

        public static List<int> add_list(List<int> la, int n)
        {
            foreach (int na in la)
            {
                if (na == n)
                    return la;
            }
            la.Add(n);
            return la;
        }
        public static List<int> combin(List<int> la, List<int> lb)//合并复制到一个新的List里
        {
            List<int> ll = new List<int>();
            foreach (int n in la)
                add_list(ll, n);
            foreach (int n in lb)
                add_list(ll, n);
            return ll;
        }

        public static List<int> combin(List<int> la, int[] lb)//合并复制到一个新的List里
        {
            List<int> ll = new List<int>();
            foreach (int n in la)
                add_list(ll, n);
            foreach (int n in lb)
                add_list(ll, n);
            return ll;
        }
        public static bool is_same_chain_node(int[] node1, int[] node2)
        {
            if (node1.Length == 4 && node2.Length == 4)
            {
                if (node1[0] == node2[0]
                    && node1[1] == node2[1]
                    && node1[2] == node2[2])
                    return true;
            }
            return false;
        }

        //辅助函数
        public static List<List<number>> numbers_combination(number[] ns, int dim)
        {
            List<List<number>> ret = new List<List<number>>();
            if (dim != 2 && dim != 3 && dim != 4)
                throw new Exception("only support 2,3,4 combination");
            for (int i = 0; i < ns.Length - dim + 1; ++i)
            {
                number ni = ns[i];
                for (int j = i + 1; j < ns.Length - dim + 2; ++j)
                {
                    number nj = ns[j];
                    if (dim == 2)
                    {
                        List<number> nlist = new List<number>();
                        nlist.Add(ni);
                        nlist.Add(nj);
                        ret.Add(nlist);
                        continue;
                    }
                    for (int k = j + 1; k < ns.Length - dim + 3; ++k)
                    {
                        number nk = ns[k];
                        if (dim == 3)
                        {
                            List<number> nlist = new List<number>();
                            nlist.Add(ni);
                            nlist.Add(nj);
                            nlist.Add(nk);
                            ret.Add(nlist);
                            continue;
                        }
                        for (int l = k + 1; l < ns.Length - dim + 4; ++l)
                        {
                            List<number> nlist = new List<number>();
                            nlist.Add(ni);
                            nlist.Add(nj);
                            nlist.Add(nk);
                            nlist.Add(ns[l]);
                            ret.Add(nlist);
                            continue;
                        }
                    }
                }
            }
            return ret;
        }

        public static List<int> get_cand_pos(iterator it,int cand)
        {
            List<int> ret = new List<int>();
            for(int i=1;i<=9;++i)
            {
                if (it[i - 1, cand - 1] == pubfun.Flag.normal)
                    ret.Add(i);
            }
            return ret;
        }

        public static bool find<T>(List<T> ts,T t) /*where T:IComparable*/
        {
            foreach(T tt in ts)
            {
                if (tt.Equals(t))
                    return true;
            }
            return false;
        }
        public static bool find<T>(T[] ts, T t) /*where T:IComparable*/
        {
            foreach (T tt in ts)
            {
                if (tt.Equals(t))
                    return true;
            }
            return false;
        }

        public static void swap<T>(ref T obj1, ref T obj2)
        {
            T obj = obj1;
            obj1 = obj2;
            obj2 = obj;
        }

    }
}